﻿using Opc.Ua;
using Opc.Ua.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace OpcTest828D
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }


        #region Fields
        private UAClientHelperAPI m_Server = null;
        private Subscription m_Subscription;
        private UInt16 m_NameSpaceIndex = 2;

        #endregion

        private void Connect_btn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                m_Server = new UAClientHelperAPI();

                //让程序自动接收服务器证书
                m_Server.CertificateValidationNotification += new CertificateValidationEventHandler(m_Server_CertificateEvent);

                // Connect with URL from Server URL text box
                string u = url_txt.Text;
                m_Server.Connect(url_txt.Text, "http://opcfoundation.org/UA/SecurityPolicy#None", MessageSecurityMode.None, true, "OpcUaClient", "SUNRISE");
                //m_Server.Connect(txtServerUrl.Text, "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15", MessageSecurityMode.None, true, "OpcUaClient", "SUNRISE");
                Console.WriteLine("connect success  ");
            }
            catch (Exception ex)
            {
                Console.WriteLine("connect failed  " + ex.Message);
            }
        }

        void m_Server_CertificateEvent(CertificateValidator validator, CertificateValidationEventArgs e)
        {
            // Accept all certificate -> better ask user
            e.Accept = true;
        }

        private void Read_btn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                List<string> nodesToRead = new List<string>();
                List<string> results = new List<string>();

                // Add the two variable NodeIds to the list of nodes to read
                // NodeId is constructed from 
                // - the identifier text in the text box
                // - the namespace index collected during the server connect
                nodesToRead.Add(new NodeId(rs_txt.Text, m_NameSpaceIndex).ToString());
                // Read the values
                results = m_Server.ReadValues(nodesToRead);

                Console.WriteLine(results[0]);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Read failed:\n\n" + ex.Message);
            }
        }

        private void ReadMul_btn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                List<string> nodesToRead = new List<string>();
                List<string> results = new List<string>();

                // Add the two variable NodeIds to the list of nodes to read
                // NodeId is constructed from 
                // - the identifier text in the text box
                // - the namespace index collected during the server connect
                nodesToRead.Add(new NodeId(r1_txt.Text, m_NameSpaceIndex).ToString());
                nodesToRead.Add(new NodeId(r2_txt.Text, m_NameSpaceIndex).ToString());
                nodesToRead.Add(new NodeId(r3_txt.Text, m_NameSpaceIndex).ToString());
                // Read the values
                results = m_Server.ReadValues(nodesToRead);

                Console.WriteLine(results[0]);
                Console.WriteLine(results[1]);
                Console.WriteLine(results[2]);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Read failed:\n\n" + ex.Message);
            }
        }

        private void WriteMul_btn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                List<string> nodesToWrite = new List<string>();
                List<string> values = new List<string>();

                nodesToWrite.Add(new NodeId(w1_txt.Text, m_NameSpaceIndex).ToString());
                nodesToWrite.Add(new NodeId(w2_txt.Text, m_NameSpaceIndex).ToString());
                values.Add(v1_txt.Text);
                values.Add(v2_txt.Text);

                m_Server.WriteValues(values, nodesToWrite);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Writing new value failed:\n\n" + ex.Message);
            }
        }

        private void Sub_btn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if(sub_btn.Content.ToString() == "停止")
                {

                    m_Server.RemoveSubscription("mySub");
                    sub_btn.Content = "订阅";
                    return;
                }


                List<string> nodesToSub = new List<string>();
                List<string> tags = new List<string>();

                // Add the two variable NodeIds to the list of nodes to read
                // NodeId is constructed from 
                // - the identifier text in the text box
                // - the namespace index collected during the server connect
                nodesToSub.Add(new NodeId(r1_txt.Text, m_NameSpaceIndex).ToString());
                tags.Add("item1");

                nodesToSub.Add(new NodeId(r2_txt.Text, m_NameSpaceIndex).ToString());
                tags.Add("item2");

                nodesToSub.Add(new NodeId(r3_txt.Text, m_NameSpaceIndex).ToString());
                tags.Add("item3");


                // Create subscription
                m_Server.CreatSubcription("mySub", 200, 200, nodesToSub, tags, ClientApi_ValueChanged);
                sub_btn.Content = "停止";
            }
            catch (Exception ex)
            {
                MessageBox.Show("Establishing data monitoring failed:\n\n" + ex.Message);
            }


            //另一种订阅方式
            //if (m_Subscription == null)
            //{
            //    try
            //    {  
            //        m_Subscription = m_Server.Subscribe(200);
            //        m_Server.ItemChangedNotification += new MonitoredItemNotificationEventHandler(ClientApi_ValueChanged);
            //        sub_btn.Content = "停止";

            //        // Create first monitored item
            //        m_Server.AddMonitoredItem(m_Subscription, new NodeId(r1_txt.Text, m_NameSpaceIndex).ToString(), "item1", 100);


            //        // Create second monitored item
            //        m_Server.AddMonitoredItem(m_Subscription, new NodeId(r2_txt.Text, m_NameSpaceIndex).ToString(), "item2", 100);
            //        m_Server.AddMonitoredItem(m_Subscription, new NodeId(r3_txt.Text, m_NameSpaceIndex).ToString(), "item3", 100);
            //    }
            //    catch (Exception ex)
            //    {
            //        MessageBox.Show("Establishing data monitoring failed:\n\n" + ex.Message);
            //    }
            //}
            //else
            //{
            //    try
            //    {
            //        m_Server.RemoveSubscription(m_Subscription);
            //        m_Subscription = null;

            //        sub_btn.Content = "订阅";
        
            //    }
            //    catch (Exception ex)
            //    {
            //        MessageBox.Show("Stopping data monitoring failed:\n\n" + ex.Message);
            //    }
            //}
        }




        private void ClientApi_ValueChanged(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
        {
            try
            {
                MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;
                if (notification == null)
                {
                    return;
                }

                if (monitoredItem.DisplayName == "item1")
                {
                    // Get the according item
                    Console.WriteLine("s1:  " + notification.Value.SourceTimestamp.ToString()+ " ==>  " + notification.Value.WrappedValue.ToString());
                }

                if (monitoredItem.DisplayName == "item2")
                {
                    // Get the according item
                    Console.WriteLine("s2:  " + notification.Value.SourceTimestamp.ToString() + " ==>  " + notification.Value.WrappedValue.ToString());
                }

                if (monitoredItem.DisplayName == "item3")
                {
                    // Get the according item
                    Console.WriteLine("s3:  " + notification.Value.SourceTimestamp.ToString() + " ==>  " + notification.Value.WrappedValue.ToString());
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unexpected error in the data change callback:\n\n" + ex.Message);
            }
        }

    }
}
